# 获取顶层传递的选项
set(COMPONENTS_TO_BUILD "")

# 自动遍历 components 目录下的所有子目录
file(GLOB COMPONENT_DIRS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "*/CMakeLists.txt")

message(STATUS "Components to build: ${COMPONENT_DIRS}")

# 提取组件名称（去掉路径和文件名）
foreach(COMPONENT_DIR IN LISTS COMPONENT_DIRS)

    get_filename_component(COMPONENT_NAME "${COMPONENT_DIR}" DIRECTORY)
    message(STATUS "Component name: ${COMPONENT_NAME}")
    if(BUILD_${COMPONENT_NAME})
        list(APPEND COMPONENTS_TO_BUILD ${COMPONENT_NAME})
    endif()

endforeach()

# 确保组件名称是唯一的
list(REMOVE_DUPLICATES COMPONENTS_TO_BUILD)
message(STATUS "Components to build: ${COMPONENTS_TO_BUILD}")

# 添加并记录每个组件
foreach(COMPONENT IN LISTS COMPONENTS_TO_BUILD)
    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${COMPONENT}/CMakeLists.txt")
        # 添加组件的子目录
        add_subdirectory(${COMPONENT})

        # 记录构建的库
        list(APPEND COMPONENT_LIBS ${COMPONENT})
    endif()
endforeach()

# 将构建的库列表传递回顶层
set(COMPONENT_LIBS ${COMPONENT_LIBS} PARENT_SCOPE)

# 说明
## PARENT_SCOPE 是 CMake 中用于在父作用域中设置变量的关键字。
## 它允许你在当前作用域（例如一个 CMakeLists.txt 文件或一个函数/宏内部）修改变量的值，并将这个修改后的值传递给调用者的上下文（即父作用域）。
## 这在处理多层嵌套的 CMakeLists.txt 文件时非常有用，尤其是在子目录中需要传递信息回顶层 CMakeLists.txt 时。
## 在这个例子中，我们使用 PARENT_SCOPE 将 COMPONENT_LIBS 列表传递回顶层 CMakeLists.txt 文件，以便在顶层构建系统中使用这些库。

# PARENT_SCOPE 常用于以下场景：

## 从子目录传递信息回父目录：例如，在 components/CMakeLists.txt 中构建多个库，并将这些库的名称传递回顶层 CMakeLists.txt，以便在主程序中链接这些库。
## 函数/宏中返回值：在 CMake 函数或宏中，如果你想返回一个值给调用者，可以使用 PARENT_SCOPE 来修改父作用域中的变量。

# PARENT_SCOPE 与 CACHE 和 FORCE 的区别
## PARENT_SCOPE：只影响父作用域，不会影响当前作用域。它通常用于从子目录或函数中传递信息回父目录。
## CACHE：将变量存储在 CMake 缓存中，使其在整个构建过程中可见，并且可以在命令行中覆盖。通常用于用户配置选项。
## FORCE：强制设置变量的值，即使该变量已经在缓存中存在。通常用于覆盖用户配置。


## list(REMOVE_DUPLICATES COMPONENTS_TO_BUILD) 用于从列表中移除重复的元素。